home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-11-10 | 43.4 KB | 1,592 lines | [TEXT/PJMM] |
- unit WESelecting;
-
- { WASTE PROJECT }
- { Drawing Selections, Activating, Updating, Scrolling, etc. }
-
- { Copyright © 1993-1994 Marco Piovanelli }
- { All Rights Reserved }
-
- interface
- uses
- WELineLayout;
-
- function WEGetOffset (thePoint: LongPoint;
- var edge: SignedByte;
- hWE: WEHandle): LongInt;
- procedure WEGetPoint (offset: LongInt;
- var thePoint: LongPoint;
- var lineHeight: Integer;
- hWE: WEHandle);
- function WEGetHiliteRgn (rangeStart, rangeEnd: LongInt;
- hWE: WEHandle): RgnHandle;
- procedure _WEDrawCaret (offset: LongInt;
- hWE: WEHandle);
- procedure _WEBlinkCaret (hWE: WEHandle);
- procedure _WEHiliteRange (rangeStart, rangeEnd: LongInt;
- hWE: WEHandle);
- procedure WEUpdate (updateRgn: RgnHandle;
- hWE: WEHandle);
- procedure WEScroll (hOffset, vOffset: LongInt;
- hWE: WEHandle);
- function _WEScrollIntoView (offset: LongInt;
- hWE: WEHandle): Boolean;
- procedure WESelView (hWE: WEHandle);
- procedure WEActivate (hWE: WEHandle);
- procedure WEDeactivate (hWE: WEHandle);
- function WEIsActive (hWE: WEHandle): Boolean;
- procedure _WEDoArrowKey (arrow: Integer;
- modifiers: Integer;
- hWE: WEHandle);
- function WEAdjustCursor (mouseLoc: Point;
- mouseRgn: RgnHandle;
- hWE: WEHandle): Boolean;
- procedure WEIdle (var maxSleep: LongInt;
- hWE: WEHandle);
- procedure WESetSelection (selStart, selEnd: LongInt;
- hWE: WEHandle);
- procedure WESetAlignment (alignment: SignedByte;
- hWE: WEHandle);
- procedure WEFindWord (offset: LongInt;
- edge: SignedByte;
- var wordStart, wordEnd: LongInt;
- hWE: WEHandle);
- procedure WEFindLine (offset: LongInt;
- edge: SignedByte;
- var lineStart, lineEnd: LongInt;
- hWE: WEHandle);
- function WECharByte (offset: LongInt;
- hWE: WEHandle): Integer;
- function WECharType (offset: LongInt;
- hWE: WEHandle): Integer;
-
- implementation
- uses
- Drag, ExternQD, QDOffscreen, TextServices;
-
- { If WASTE_OBJECTS_ARE_GLYPHS is TRUE, WEGetOffset treats embedded objects }
- { like ordinary glyphs and never returns kObjectEdge in the edge parameter: }
- { as a result, clicking in the middle of an object always positions the caret either }
- { to the left or to the right of the object. }
-
- { If WASTE_OBJECTS_ARE_GLYPHS is FALSE, WEGetOffset returns kObjectEdge in }
- { the edge parameter when thePoint is in the middle half of an object: as a result, }
- { clicking in the middle of an object immediately _selects_ the object, so that a second }
- { click immediately following triggers the 'clik' callback (this can be handy to make }
- { sound objects play when they are double-clicked. }
-
- {$SETC WASTE_OBJECTS_ARE_GLYPHS = TRUE}
-
- const
-
- { values for _WEArrowOffset action parameter: }
- { plain arrow keys }
- kGoLeft = 0;
- kGoRight = 1;
- kGoUp = 2;
- kGoDown = 3;
-
- { modifiers }
- kOption = 4;
- kCommand = 8;
-
- { option + arrow combos }
- kGoWordStart = kGoLeft + kOption;
- kGoWordEnd = kGoRight + kOption;
- kGoTextStart = kGoUp + kOption;
- kGoTextEnd = kGoDown + kOption;
-
- { command + arrow combos }
- kGoLineStart = kGoLeft + kCommand;
- kGoLineEnd = kGoRight + kCommand;
- kGoPageStart = kGoUp + kCommand;
- kGoPageEnd = kGoDown + kCommand;
-
- procedure ClearHiliteBit;
- inline
- $08B8, $0007, $0938; { bclr #7, HiliteMode }
-
- function WEGetOffset (thePoint: LongPoint;
- var edge: SignedByte;
- hWE: WEHandle): LongInt;
-
- { given a long point in local coordinates, }
- { find the text offset corresponding to the nearest glyph }
-
- var
- pWE: WEPtr;
- lineIndex: LongInt;
- pixelWidth: Fixed;
- saveWELock: Boolean;
-
- function SLPixelToChar (pLine: LinePtr;
- pAttrs: WERunAttributesPtr;
- pSegment: Ptr;
- segmentStart, segmentLength: LongInt;
- styleRunPosition: JustStyleCode): Boolean;
- var
- slop, width, subWidth: Fixed;
- cType: Integer;
- begin
- SLPixelToChar := false;
-
- { if this is the first style run on the line, subtract pen indent from pixelWidth }
- if (styleRunPosition <= smLeftStyleRun) then
- pixelWidth := pixelWidth - BSL(_WECalcPenIndent(pLine^.lineSlop, pWE^.alignment), 16);
-
- { if pixel width is gone negative already, the point is on the trailing edge of first glyph }
- if (pixelWidth < 0) then
- begin
- WEGetOffset := segmentStart;
- edge := kTrailingEdge;
- SLPixelToChar := true;
- Exit(SLPixelToChar);
- end;
-
- if (pAttrs^.runStyle.tsObject <> kNullObject) then
- begin
-
- { EMBEDDED OBJECT }
- { calculate object width as Fixed }
- width := BSL(WEObjectDescHandle(pAttrs^.runStyle.tsObject)^^.objectSize.h, 16);
-
- { subtract object width from pixelWidth }
- pixelWidth := pixelWidth - width;
-
- {$IFC WASTE_OBJECTS_ARE_GLYPHS}
-
- { find out whether the point is in the leftmost half of the object, }
- { in the rightmost half or past the object }
- subWidth := BSR(width, 1); { divide by two }
- if (pixelWidth + subWidth < 0) then
- begin
- WEGetOffset := segmentStart;
- edge := kLeadingEdge; { point is in leftmost half of object }
- end
- else
- begin
- WEGetOffset := segmentStart + 1;
- if (pixelWidth < 0) then
- edge := kTrailingEdge { point is in rightmost half of object }
- else
- edge := kLeadingEdge; { point is past object }
- end;
-
- {$ELSEC}
-
- { find out whether the point is in the leftmost quarter of the object, }
- { in the middle half, in the rightmost quarter or past the object }
- subWidth := BSR(width, 2); { divide by four }
- if (pixelWidth + subWidth < 0) then
- begin
- WEGetOffset := segmentStart;
- if (pixelWidth + width < subWidth) then
- edge := kLeadingEdge { point is in leftmost quarter of object }
- else
- edge := kObjectEdge; { point is in middle half of object }
- end
- else
- begin
- WEGetOffset := segmentStart + 1;
- if (pixelWidth < 0) then
- edge := kTrailingEdge { point is in rightmost quarter of object }
- else
- edge := kLeadingEdge; { point is past object }
- end;
-
- {$ENDC}
-
- end
- else
- begin
-
- { REGULAR TEXT }
- { if this is the last segment on the line, strip the last blank character (if any), }
- { unless it is the last non-CR character in the whole text stream }
- if (not Odd(styleRunPosition)) then
- if (segmentStart + segmentLength < pWE^.textLength) | (Ptr(LongInt(pSegment) + segmentLength - 1)^ = kEOL) then
- begin
- cType := CharType(pSegment, segmentLength - 1);
- if (BitAnd(cType, smcTypeMask + smcClassMask) = smCharPunct + smPunctBlank) then
- if (BitAnd(cType, smcDoubleMask) = 0) then
- segmentLength := segmentLength - 1
- else
- segmentLength := segmentLength - 2;
- end;
-
- { calculate slop for this text segment (justified text only) }
- if (pWE^.alignment = weJustify) then
- slop := FixMul(NPortionText(pSegment, segmentLength, styleRunPosition, Point(kOneToOneScaling), Point(kOneToOneScaling)), pLine^.lineJustAmount)
- else
- slop := 0;
-
- { call PixelToChar for this segment }
- WEGetOffset := segmentStart + NPixel2Char(pSegment, segmentLength, slop, pixelWidth, Boolean(edge), width, styleRunPosition, Point(kOneToOneScaling), Point(kOneToOneScaling));
-
- { update pixelWidth for next iteration }
- pixelWidth := width;
-
- end;
-
- { if pixelWidth has gone negative, we're finished; otherwise go to next run }
- if (pixelWidth < 0) then
- SLPixelToChar := true;
-
- end; { SLPixelToChar }
-
- begin
-
- { lock the WE record }
- saveWELock := _WESetHandleLock(hWE, true);
- pWE := hWE^;
-
- { offset thePoint so that it is relative to the top left corner of the destination rectangle }
- thePoint.v := thePoint.v - pWE^.destRect.top;
- thePoint.h := thePoint.h - pWE^.destRect.left;
-
- { if the point is above the destination rect, return zero }
- if (thePoint.v < 0) then
- begin
- WEGetOffset := 0;
- edge := kTrailingEdge;
- end
- else
-
- { if the point is below the last line, return last char offset }
- if (thePoint.v >= WEGetHeight(0, maxLongInt, hWE)) then
- begin
- WEGetOffset := pWE^.textLength;
- edge := kLeadingEdge;
- end
- else
- begin
-
- { find the line index corresponding to the vertical pixel offset }
- lineIndex := _WEPixelToLine(thePoint.v, hWE);
-
- { express the horizontal pixel offset as a Fixed value }
- pixelWidth := BSL(thePoint.h, 16);
-
- { walk through the segments on this line calling PixelToChar }
- _WESegmentLoop(lineIndex, lineIndex, SLPixelToChar, hWE);
-
- end; { else }
-
- { unlock the WE record }
- IgnoreBoolean(_WESetHandleLock(hWE, saveWELock));
-
- end; { WEGetOffset }
-
- procedure WEGetPoint (offset: LongInt;
- var thePoint: LongPoint;
- var lineHeight: Integer;
- hWE: WEHandle);
-
- { given a byte offset into the text, find the corresponding glyph position }
- { this routine is useful for highlighting the text and for positioning the caret }
-
- var
- pWE: WEPtr;
- pLine: LinePeek;
- lineIndex: LongInt;
- saveWELock: Boolean;
-
- function SLCharToPixel (pLine: LinePtr;
- pAttrs: WERunAttributesPtr;
- pSegment: Ptr;
- segmentStart, segmentLength: LongInt;
- styleRunPosition: JustStyleCode): Boolean;
- var
- slop: Fixed;
- width: Integer;
- isInSegment: Boolean;
- begin
-
- { is offset within this segment? }
- isInSegment := (offset < segmentStart + segmentLength);
-
- { if this is the first style run on the line, add pen indent to thePoint.h }
- if (styleRunPosition <= smLeftStyleRun) then
- thePoint.h := thePoint.h + _WECalcPenIndent(pLine^.lineSlop, pWE^.alignment);
-
- if (pAttrs^.runStyle.tsObject <> kNullObject) then
- begin
-
- { EMBEDDED OBJECT }
- if (isInSegment) then
- width := 0
- else
- width := WEObjectDescHandle(pAttrs^.runStyle.tsObject)^^.objectSize.h;
-
- end
- else
- begin
-
- { REGULAR TEXT }
- { calculate slop for this text segment (justified text only) }
- if (pWE^.alignment = weJustify) then
- slop := FixMul(NPortionText(pSegment, segmentLength, styleRunPosition, Point(kOneToOneScaling), Point(kOneToOneScaling)), pLine^.lineJustAmount)
- else
- slop := 0;
-
- { call CharToPixel to get width of segment up to specified offset }
- width := NChar2Pixel(pSegment, segmentLength, slop, offset - segmentStart, smHilite, styleRunPosition, Point(kOneToOneScaling), Point(kOneToOneScaling));
-
- end;
-
- { advance thePoint.h by the width of this segment }
- thePoint.h := thePoint.h + width;
-
- { drop out of loop when we reach offset }
- SLCharToPixel := isInSegment;
-
- end; { SLCharToPixel }
-
- begin
-
- { lock the WE record }
- saveWELock := _WESetHandleLock(hWE, true);
- pWE := hWE^;
-
- { the base point is the top left corner of the destination rectangle }
- thePoint := pWE^.destRect.topLeft;
-
- { first of all find the line on which the glyph lies }
- lineIndex := WEOffsetToLine(offset, hWE);
-
- { calculate the vertical coordinate and the line height }
- pLine := @pWE^.hLines^^[lineIndex];
- thePoint.v := thePoint.v + pLine^.first.lineOrigin;
- lineHeight := pLine^.second.lineOrigin - pLine^.first.lineOrigin;
-
- if ((offset = pWE^.textLength) & (WEGetChar(offset - 1, hWE) = CHR(kEOL))) then
- begin
-
- { SPECIAL CASE: if offset is past the last character and }
- { the last character is a carriage return, return a point below the last line }
-
- thePoint.v := thePoint.v + lineHeight;
- thePoint.h := thePoint.h + _WECalcPenIndent(pWE^.destRect.right - pWE^.destRect.left, pWE^.alignment);
- end
- else
-
- { to get the horizontal coordinate, walk through the style runs on this line }
- _WESegmentLoop(lineIndex, lineIndex, SLCharToPixel, hWE);
-
- { pin the horizontal coordinate to the destination rectangle }
- thePoint.h := _WEPinInRange(thePoint.h, pWE^.destRect.left, pWE^.destRect.right);
-
- { unlock the WE record }
- IgnoreBoolean(_WESetHandleLock(hWE, saveWELock));
-
- end; { WEGetPoint }
-
- procedure WEFindLine (offset: LongInt;
- edge: SignedByte;
- var lineStart, lineEnd: LongInt;
- hWE: WEHandle);
- var
- pWE: WEPtr;
- pLine: LineArrayPtr;
- begin
- pWE := hWE^;
- pLine := @pWE^.hLines^^[WEOffsetToLine(offset, hWE)];
- lineStart := pLine^[0].lineStart;
- lineEnd := pLine^[1].lineStart;
- end; { WEFindLine }
-
- function _WEGetContext (offset: LongInt;
- var contextStart, contextEnd: LongInt;
- hWE: WEHandle): Integer;
-
- { This function finds a range of characters ("context"), all belonging to the same script }
- { and centered around the specified offset. }
- { The function result is the ID of a font belonging to this script. }
- { Ideally, the context should consist of a whole script run, but in practice the returned }
- { context can be narrower, for performance and other reasons (see below) }
-
- var
- index, saveIndex, saveRunEnd: LongInt;
- runInfo: WERunInfo;
- script1, script2: ScriptCode;
- begin
- if BTST(hWE^^.flags, weFNonRoman) then
- begin
-
- { if more than one script is installed, limit the search of script run boundaries }
- { to a single line, for speed's sake }
- WEFindLine(offset, kLeadingEdge, contextStart, contextEnd, hWE);
-
- { find the style run the specified offset is in }
- index := _WEOffsetToRun(offset, hWE);
- _WEGetIndStyle(index, runInfo, hWE);
-
- { return the style run font as function result }
- _WEGetContext := runInfo.runAttrs.runStyle.tsFont;
-
- { find the script code associated with this style run }
- script1 := Font2Script(runInfo.runAttrs.runStyle.tsFont);
-
- { save index and runInfo.runEnd for the second while loop }
- saveIndex := index;
- saveRunEnd := runInfo.runEnd;
-
- { walk backwards across style runs preceding offset, looking for a script run boundary }
- while (runInfo.runStart > contextStart) do
- begin
- index := index - 1;
- _WEGetIndStyle(index, runInfo, hWE);
- script2 := Font2Script(runInfo.runAttrs.runStyle.tsFont);
- if (script1 <> script2) then
- begin
- contextStart := runInfo.runEnd;
- Leave;
- end;
- end; { while }
-
- { restore index and runInfo.runEnd }
- index := saveIndex;
- runInfo.runEnd := saveRunEnd;
-
- { walk forward across style runs following offset, looking for a script run boundary }
- while (runInfo.runEnd < contextEnd) do
- begin
- index := index + 1;
- _WEGetIndStyle(index, runInfo, hWE);
- script2 := Font2Script(runInfo.runAttrs.runStyle.tsFont);
- if (script1 <> script2) then
- begin
- contextEnd := runInfo.runStart;
- Leave;
- end;
- end; { while }
-
- end
- else
- begin
-
- { only the Roman script is enabled: the whole text constitutes one script run }
- _WEGetContext := systemFont;
- contextStart := 0;
- contextEnd := hWE^^.textLength;
- end;
-
- { make sure the range identified by contextStart/contextEnd is contained within }
- { the 32K byte range centered around the specified offset }
- { the reason for this is that many Script Manager routines (e.g. FindWord and CharByte) }
- { only accept 16-bit offsets, rather than 32-bit offsets }
-
- contextStart := _WEPinInRange(contextStart, offset - (maxint div 2), offset);
- contextEnd := _WEPinInRange(contextEnd, offset, offset + (maxint div 2));
-
- end; { _WEGetContext }
-
- function _WEGetRestrictedContext (offset: LongInt;
- var contextStart, contextEnd: LongInt;
- hWE: WEHandle): Integer;
-
- { This function finds a range of characters ("context"), all belonging to the same script }
- { and centered around the specified offset. }
- { This function returns a script run subrange and is more efficient than }
- { _WEGetContext because it doesn't try to find the script boundaries accurately. }
-
- var
- runInfo: WERunInfo;
- begin
-
- { just find the style run the specified offset is in }
- WEGetRunInfo(offset, runInfo, hWE);
- contextStart := runInfo.runStart;
- contextEnd := runInfo.runEnd;
- _WEGetRestrictedContext := runInfo.runAttrs.runStyle.tsFont;
-
- { make sure the range identified by contextStart/contextEnd is contained within }
- { the 32K byte range centered around the specified offset }
- { the reason for this is that many Script Manager routines (e.g. FindWord and CharByte) }
- { only accept 16-bit offsets, rather than 32-bit offsets }
-
- contextStart := _WEPinInRange(contextStart, offset - (maxint div 2), offset);
- contextEnd := _WEPinInRange(contextEnd, offset, offset + (maxint div 2));
-
- end; { _WEGetRestrictedContext }
-
- procedure WEFindWord (offset: LongInt;
- edge: SignedByte;
- var wordStart, wordEnd: LongInt;
- hWE: WEHandle);
- var
- pWE: WEPtr;
- contextStart, contextEnd: LongInt;
- hText: Handle;
- wordBreaks: OffsetTable;
- saveFont: Integer;
- savePort: GrafPtr;
- saveTextLock: Boolean;
- begin
- pWE := hWE^;
- hText := pWE^.hText;
-
- { set up the port }
- GetPort(savePort);
- SetPort(pWE^.port);
-
- { find a script context containing the specified offset }
- { (words cannot straddle script boundaries) }
- { and set the port font to the corresponding script font }
-
- saveFont := pWE^.port^.txFont;
- TextFont(_WEGetContext(offset, contextStart, contextEnd, hWE));
-
- { lock the text }
- saveTextLock := _WESetHandleLock(hText, true);
-
- { find word breaks }
- FindWord(Ptr(LongInt(hText^) + contextStart), contextEnd - contextStart, offset - contextStart, Boolean(edge), nil, wordBreaks);
-
- { unlock the text }
- IgnoreBoolean(_WESetHandleLock(hText, saveTextLock));
-
- { restore font and port }
- TextFont(saveFont);
- SetPort(savePort);
-
- { calculate wordStart and wordEnd relative to the beginning of the text }
- wordStart := contextStart + wordBreaks[0].offFirst;
- wordEnd := contextStart + wordBreaks[0].offSecond;
-
- end; { WEFindWord }
-
- function WECharByte (offset: LongInt;
- hWE: WEHandle): Integer;
- var
- pWE: WEPtr;
- contextStart, contextEnd: LongInt;
- saveFont: Integer;
- savePort: GrafPtr;
- begin
- WECharByte := smSingleByte;
- pWE := hWE^;
-
- { exit now if there is no double-byte script system installed }
- if (not BTST(pWE^.flags, weFDoubleByte)) then
- Exit(WECharByte);
-
- { sanity check: make sure offset is within allowed bounds }
- if ((offset < 0) or (offset >= pWE^.textLength)) then
- Exit(WECharByte);
-
- { save the port }
- GetPort(savePort);
- SetPort(pWE^.port);
-
- { find a script context containing the specified offset }
- { and set the port font to the corresponding script font }
- saveFont := pWE^.port^.txFont;
- TextFont(_WEGetRestrictedContext(offset, contextStart, contextEnd, hWE));
-
- { pass CharByte a pointer to the beginning of the style run }
- { CharByte is guaranteed not to move memory, so the text needn't be locked }
- WECharByte := CharByte(Ptr(LongInt(pWE^.hText^) + contextStart), offset - contextStart);
-
- { restore the port font }
- TextFont(saveFont);
-
- { restore the port }
- SetPort(savePort);
-
- end; { WECharByte }
-
- function WECharType (offset: LongInt;
- hWE: WEHandle): Integer;
- var
- pWE: WEPtr;
- contextStart, contextEnd: LongInt;
- hText: Handle;
- saveFont: Integer;
- savePort: GrafPtr;
- saveTextLock: Boolean;
- begin
- WECharType := 0;
- pWE := hWE^;
- hText := pWE^.hText;
-
- { sanity check: make sure offset is within allowed bounds }
- if ((offset < 0) or (offset >= pWE^.textLength)) then
- Exit(WECharType);
-
- { save the port }
- GetPort(savePort);
- SetPort(pWE^.port);
-
- { find a script context containing the specified offset }
- { and set the port font to the corresponding script font }
- saveFont := pWE^.port^.txFont;
- TextFont(_WEGetRestrictedContext(offset, contextStart, contextEnd, hWE));
-
- { lock the text (CharType may move memory) }
- saveTextLock := _WESetHandleLock(hText, true);
-
- { pass CharType a pointer to the beginning of the style run }
- WECharType := CharType(Ptr(LongInt(hText^) + contextStart), offset - contextStart);
-
- { unlock the text }
- IgnoreBoolean(_WESetHandleLock(hText, saveTextLock));
-
- { restore the port font }
- TextFont(saveFont);
-
- { restore the port }
- SetPort(savePort);
-
- end; { WECharType }
-
- procedure _WEDrawCaret (offset: LongInt;
- hWE: WEHandle);
- var
- pWE: WEPtr;
- thePoint: LongPoint;
- caretRect: Rect;
- caretHeight: Integer;
- savePort: GrafPtr;
- saveClip: RgnHandle;
- begin
-
- { the WE record must be already locked }
- pWE := hWE^;
-
- { find the caret position using WEGetPoint }
- WEGetPoint(offset, thePoint, caretHeight, hWE);
- WELongPointToPoint(thePoint, caretRect.topLeft);
- if (caretRect.left > pWE^.destRect.left) then
- caretRect.left := caretRect.left - 1;
-
- { calculate caret rectangle }
- caretRect.bottom := caretRect.top + caretHeight;
- caretRect.right := caretRect.left + kCaretWidth;
-
- { set up the port }
- GetPort(savePort);
- SetPort(pWE^.port);
-
- { clip to the view region }
- saveClip := NewRgn;
- GetClip(saveClip);
- SetClip(pWE^.viewRgn);
-
- { draw the caret }
- InvertRect(caretRect);
-
- { restore the clip region }
- SetClip(saveClip);
- DisposeRgn(saveClip);
-
- { restore the port }
- SetPort(savePort);
-
- end; { _WEDrawCaret }
-
- procedure _WEBlinkCaret (hWE: WEHandle);
- var
- pWE: WEPtr;
- begin
-
- { the WE record must be already locked }
- pWE := hWE^;
-
- { do nothing if we're not active }
- if (not BTST(pWE^.flags, weFActive)) then
- Exit(_WEBlinkCaret);
-
- { redraw the caret, in XOR mode }
- _WEDrawCaret(pWE^.selStart, hWE);
-
- { keep track of the current caret visibility status }
- pWE^.flags := BitXor(pWE^.flags, BSL(1, weFCaretVisible));
-
- { update caretTime }
- pWE^.caretTime := TickCount;
-
- end; { _WEBlinkCaret }
-
- function WEGetHiliteRgn (rangeStart, rangeEnd: LongInt;
- hWE: WEHandle): RgnHandle;
-
- { returns the hilite region corresponding to the specified range }
- { the caller is responsible for disposing of the returned region }
- { when it's finished with it }
-
- var
- pWE: WEPtr;
- hiliteRgn: RgnHandle;
- selRect: LongRect;
- firstPoint, lastPoint: LongPoint;
- firstLineHeight, lastLineHeight: Integer;
- r: Rect;
- savePort: GrafPtr;
- saveWELock: Boolean;
- begin
-
- { lock the WE record }
- saveWELock := _WESetHandleLock(hWE, true);
- pWE := hWE^;
-
- { set up the port }
- GetPort(savePort);
- SetPort(pWE^.port);
-
- { make sure rangeStart comes before rangeEnd }
- _WEReorder(rangeStart, rangeEnd);
-
- { calculate pixel location corresponding to rangeStart }
- WEGetPoint(rangeStart, firstPoint, firstLineHeight, hWE);
-
- { calculate pixel location corresponding to rangeEnd }
- WEGetPoint(rangeEnd, lastPoint, lastLineHeight, hWE);
-
- { open a region: rects to be hilited will be accumulated in this }
- OpenRgn;
-
- if (firstPoint.v = lastPoint.v) then
- begin
-
- { selection range encompasses only one line }
- WESetLongRect(selRect, firstPoint.h, firstPoint.v, lastPoint.h, lastPoint.v + lastLineHeight);
- WELongRectToRect(selRect, r);
- FrameRect(r);
- end
- else
- begin
-
- { selection range encompasses more than one line }
- { hilite the first line }
- WESetLongRect(selRect, firstPoint.h, firstPoint.v, pWE^.destRect.right, firstPoint.v + firstLineHeight);
- WELongRectToRect(selRect, r);
- FrameRect(r);
-
- { any lines between the first and the last one? }
- if (firstPoint.v + firstLineHeight < lastPoint.v) then
- begin
-
- { hilite all the lines in-between }
- WESetLongRect(selRect, pWE^.destRect.left, firstPoint.v + firstLineHeight, pWE^.destRect.right, lastPoint.v);
- WELongRectToRect(selRect, r);
- FrameRect(r);
- end;
-
- { hilite the last line }
- WESetLongRect(selRect, pWE^.destRect.left, lastPoint.v, lastPoint.h, lastPoint.v + lastLineHeight);
- WELongRectToRect(selRect, r);
- FrameRect(r);
- end;
-
- { copy the accumulated region into a new region }
- hiliteRgn := NewRgn;
- CloseRgn(hiliteRgn);
-
- { restrict this region to the view region }
- SectRgn(hiliteRgn, pWE^.viewRgn, hiliteRgn);
-
- { restore the port }
- SetPort(savePort);
-
- { unlock the WE record }
- IgnoreBoolean(_WESetHandleLock(hWE, saveWELock));
-
- { return the hilite region }
- WEGetHiliteRgn := hiliteRgn;
-
- end; { WEGetHiliteRgn }
-
- procedure _WEHiliteRange (rangeStart, rangeEnd: LongInt;
- hWE: WEHandle);
- var
- pWE: WEPtr;
- saveClip, auxRgn, hiliteRgn: RgnHandle;
- savePen: PenState;
- savePort: GrafPtr;
- begin
-
- { the WE record must be already locked }
- pWE := hWE^;
-
- { do nothing if the specified range is empty }
- if (rangeStart = rangeEnd) then
- Exit(_WEHiliteRange);
-
- { set up the port }
- GetPort(savePort);
- SetPort(pWE^.port);
-
- { create auxiliary regions }
- saveClip := NewRgn;
- auxRgn := NewRgn;
-
- { restrict the clip region to the view rectangle }
- GetClip(saveClip);
- SectRgn(saveClip, pWE^.viewRgn, auxRgn);
- SetClip(auxRgn);
-
- { get the hilite region corresponding to the specified range }
- hiliteRgn := WEGetHiliteRgn(rangeStart, rangeEnd, hWE);
-
- { hilite the region or frame it, depending on the setting of the active flag }
- if BTST(pWE^.flags, weFActive) then
- begin
- ClearHiliteBit;
- InvertRgn(hiliteRgn);
- end
- else if BTST(pWE^.flags, weFOutlineHilite) then
- begin
- GetPenState(savePen);
- PenNormal;
- PenMode(patXor);
- ClearHiliteBit;
- FrameRgn(hiliteRgn);
- SetPenState(savePen);
- end;
-
- { restore the clip region }
- SetClip(saveClip);
-
- { dispose of all regions }
- DisposeRgn(saveClip);
- DisposeRgn(auxRgn);
- DisposeRgn(hiliteRgn);
-
- { restore the port }
- SetPort(savePort);
-
- end; { _WEHiliteRange }
-
- procedure WESetSelection (selStart, selEnd: LongInt;
- hWE: WEHandle);
- var
- pWE: WEPtr;
- oldSelStart, oldSelEnd: LongInt;
- saveWELock: Boolean;
- begin
-
- { lock the WE record }
- saveWELock := _WESetHandleLock(hWE, true);
- pWE := hWE^;
-
- { invalid the null style }
- BCLR(pWE^.flags, weFUseNullStyle);
-
- { hide the caret if it's showing }
- if BTST(pWE^.flags, weFCaretVisible) then
- _WEBlinkCaret(hWE);
-
- { range-check parameters }
- selStart := _WEPinInRange(selStart, 0, pWE^.textLength);
- selEnd := _WEPinInRange(selEnd, 0, pWE^.textLength);
-
- { set the weFAnchorIsEnd bit if selStart > selEnd, then reorder the endpoints }
- if (selStart > selEnd) then
- BSET(pWE^.flags, weFAnchorIsEnd)
- else
- BCLR(pWE^.flags, weFAnchorIsEnd);
- _WEReorder(selStart, selEnd);
-
- { get old selection range }
- oldSelStart := pWE^.selStart;
- oldSelEnd := pWE^.selEnd;
-
- { set new selection range }
- pWE^.selStart := selStart;
- pWE^.selEnd := selEnd;
-
- { REDRAW THE SELECTION }
- { skip this section if redrawing has been inhibited }
- if (not BTST(pWE^.flags, weFInhibitRecal)) then
- begin
-
- { if we're active, invert the exclusive-OR between the old range and the new range. }
- { if we're inactive, this optimization can't be used because of outline highlighting. }
- if BTST(pWE^.flags, weFActive) then
- begin
- _WEReorder(oldSelStart, selStart);
- _WEReorder(oldSelEnd, selEnd);
- _WEReorder(oldSelEnd, selStart);
- end;
-
- _WEHiliteRange(oldSelStart, oldSelEnd, hWE);
- _WEHiliteRange(selStart, selEnd, hWE);
-
- if (not BTST(pWE^.flags, weFMouseTracking)) then
- begin
-
- { redraw the caret immediately, if the selection range is empty }
- if (pWE^.selStart = pWE^.selEnd) then
- _WEBlinkCaret(hWE);
-
- { clear clickCount, unless we're tracking the mouse }
- pWE^.clickCount := 0;
-
- { scroll the selection into view, unless we're tracking the mouse }
- WESelView(hWE);
-
- end;
- end; { if redrawing not inhibited }
-
- { unlock the WE record }
- IgnoreBoolean(_WESetHandleLock(hWE, saveWELock));
-
- end; { WESetSelection }
-
- procedure WESetAlignment (alignment: SignedByte;
- hWE: WEHandle);
- begin
- if ((alignment >= weFlushLeft) and (alignment <= weJustify)) then
- if (alignment <> hWE^^.alignment) then
- begin
-
- { hide the caret if it's showing }
- if BTST(hWE^^.flags, weFCaretVisible) then
- _WEBlinkCaret(hWE);
-
- { change the alignment }
- hWE^^.alignment := alignment;
-
- { redraw the view rectangle }
- WEUpdate(nil, hWE);
- end;
- end; { WESetAlignment }
-
- function _WEArrowOffset (action: Integer;
- offset: LongInt;
- hWE: WEHandle): LongInt;
-
- { given an action code (corresponding to a modifiers + arrow key combo) }
- { and an offset into the text, find the offset of the new caret position }
-
- var
- thePoint: LongPoint;
- textLength, rangeStart, rangeEnd: LongInt;
- lineHeight: Integer;
- edge: SignedByte;
- begin
- textLength := hWE^^.textLength;
- case action of
-
- kGoLeft:
- if (offset > 0) then
- begin
- offset := offset - 1;
- if (WECharByte(offset, hWE) <> smSingleByte) then
- offset := offset - 1;
- end;
-
- kGoRight:
- if (offset < textLength) then
- begin
- if (WECharByte(offset, hWE) <> smSingleByte) then
- offset := offset + 1;
- offset := offset + 1;
- end;
-
- kGoUp:
- begin
- WEGetPoint(offset, thePoint, lineHeight, hWE);
- thePoint.v := thePoint.v - 1;
- offset := WEGetOffset(thePoint, edge, hWE);
- end;
-
- kGoDown:
- begin
- WEGetPoint(offset, thePoint, lineHeight, hWE);
- thePoint.v := thePoint.v + lineHeight;
- offset := WEGetOffset(thePoint, edge, hWE);
- end;
-
- kGoWordStart:
- begin
- WEFindWord(offset, kTrailingEdge, rangeStart, rangeEnd, hWE);
- offset := rangeStart;
- end;
-
- kGoWordEnd:
- begin
- WEFindWord(offset, kLeadingEdge, rangeStart, rangeEnd, hWE);
- offset := rangeEnd;
- end;
-
- kGoTextStart:
- offset := 0;
-
- kGoTextEnd:
- offset := textLength;
-
- kGoLineStart:
- begin
- WEFindLine(offset, kLeadingEdge, rangeStart, rangeEnd, hWE);
- offset := rangeStart;
- end;
-
- kGoLineEnd:
- begin
- WEFindLine(offset, kTrailingEdge, rangeStart, rangeEnd, hWE);
- offset := rangeEnd;
- if (offset < textLength) then
- begin
- offset := offset - 1;
- if (WECharByte(offset, hWE) <> smSingleByte) then
- offset := offset - 1;
- end;
- end;
-
- otherwise
- ;
- end; { case action }
-
- _WEArrowOffset := offset;
-
- end; { _WEArrowOffset }
-
- procedure _WEDoArrowKey (arrow: Integer;
- modifiers: Integer;
- hWE: WEHandle);
-
- { this routine is called by WEKey to handle arrow keys }
- { the WE record is guaranteed to be already locked }
-
- var
- pWE: WEPtr;
- action: Integer;
- selStart, selEnd: LongInt;
- caretLoc, anchor: LongInt;
- begin
- pWE := hWE^;
-
- { calculate the "action" parameter for _WEArrowOffset from arrow and modifiers }
- action := arrow - kArrowLeft; { possible range: 0..3 }
- if (BitAnd(modifiers, optionKey) <> 0) then
- action := action + kOption;
- if (BitAnd(modifiers, cmdKey) <> 0) then
- action := action + kCommand;
-
- { get selection range }
- selStart := pWE^.selStart;
- selEnd := pWE^.selEnd;
-
- if (BitAnd(modifiers, shiftKey) = 0) then
- begin
-
- { if selection range isn't empty, collapse it to one of the endpoints }
- if (selStart < selEnd) then
- if ((arrow = kArrowLeft) or (arrow = kArrowUp)) then
- caretLoc := selStart
- else
- caretLoc := selEnd
- else
-
- { otherwise move the insertion point }
- caretLoc := _WEArrowOffset(action, selStart, hWE);
-
- { set anchor to caretLoc, so new selection will be empty }
- anchor := caretLoc;
-
- end
- else
- begin
-
- { shift key was held down: extend the selection rather than replacing it }
- { find out which selection boundary is the anchor and which is the free endpoint }
- if BTST(pWE^.flags, weFAnchorIsEnd) then
- begin
- anchor := selEnd;
- caretLoc := selStart;
- end
- else
- begin
- anchor := selStart;
- caretLoc := selEnd;
- end;
-
- { move the free endpoint }
- caretLoc := _WEArrowOffset(action, caretLoc, hWE);
-
- end;
-
- { select the new selection }
- WESetSelection(anchor, caretLoc, hWE);
-
- end; { _WEDoArrowKey }
-
- function WEAdjustCursor (mouseLoc: Point;
- mouseRgn: RgnHandle;
- hWE: WEHandle): Boolean;
-
- { Call WEAdjustCursor to set the cursor shape when the mouse is in the view rectangle. }
- { MouseRgn should be either a valid region handle or NIL. }
- { If mouseRgn is supplied (i.e., if it's not NIL), it is intersected with a region }
- { in global coordinates within which the cursor is to retain its shape. }
- { WEAdjustCursor returns TRUE if the cursor has been set. }
- { Your application should set the cursor only if WEAdjustCursor returns FALSE. }
-
- var
- pWE: WEPtr;
- auxRgn, hiliteRgn: RgnHandle;
- cursorType: (kIBeam, kArrow);
- portDelta: Point;
- savePort: GrafPtr;
- saveWELock: Boolean;
- begin
- WEAdjustCursor := false;
- cursorType := kIBeam;
-
- { lock the WE record }
- saveWELock := _WESetHandleLock(hWE, true);
- pWE := hWE^;
-
- { set up the port }
- GetPort(savePort);
- SetPort(pWE^.port);
-
- { calculate delta between the local coordinate system and the global one }
- portDelta := Point(0);
- LocalToGlobal(portDelta);
-
- { calculate the visible portion of the view rectangle, in global coordinates }
- auxRgn := NewRgn;
- CopyRgn(pWE^.viewRgn, auxRgn);
- SectRgn(auxRgn, pWE^.port^.visRgn, auxRgn);
- OffsetRgn(auxRgn, portDelta.h, portDelta.v);
-
- if PtInRgn(mouseLoc, auxRgn) then
- begin
-
- { mouse is within view rectangle: it's up to us to set the cursor }
- WEAdjustCursor := true;
-
- { if drag-and-drop is enabled, see if the mouse is within current selection }
- if BTST(pWE^.flags, weFDragAndDrop) then
- if (pWE^.selStart < pWE^.selEnd) then
- begin
-
- { get current hilite region in global coordinates }
- hiliteRgn := WEGetHiliteRgn(pWE^.selStart, pWE^.selEnd, hWE);
- OffsetRgn(hiliteRgn, portDelta.h, portDelta.v);
-
- { if mouse is within selection, set cursor to an arrow, else to an I-beam }
- { (actually, we still use an I-beam if less than DoubleTime ticks have elapsed }
- { since the last mouse click, so that the cursor doesn't turn into an arrow while }
- { triple-clicking + dragging a range of lines) }
-
- if (PtInRgn(mouseLoc, hiliteRgn) and (TickCount > pWE^.clickTime + GetDblTime)) then
- begin
- cursorType := kArrow; { use arrow cursor }
- CopyRgn(hiliteRgn, auxRgn);
- end
- else
- DiffRgn(auxRgn, hiliteRgn, auxRgn);
-
- { dispose of the hilite region }
- DisposeRgn(hiliteRgn);
-
- end; { if drag-and-drop is enabled }
-
- { set the cursor }
- if (cursorType = kIBeam) then
- SetCursor(GetCursor(iBeamCursor)^^)
- else
- SetCursor(GetQDGlobals^.arrow);
-
- { set mouseRgn, if provided }
- if (mouseRgn <> nil) then
- SectRgn(mouseRgn, auxRgn, mouseRgn);
-
- end
- else
-
- { mouse is outside view rectangle: don't set the cursor; subtract viewRgn from mouseRgn }
- if (mouseRgn <> nil) then
- DiffRgn(mouseRgn, auxRgn, mouseRgn);
-
- { dispose of the temporary region }
- DisposeRgn(auxRgn);
-
- { restore the port }
- SetPort(savePort);
-
- { unlock the WE record }
- IgnoreBoolean(_WESetHandleLock(hWE, saveWELock));
-
- end; { WEAdjustCursor }
-
- procedure WEIdle (var maxSleep: LongInt;
- hWE: WEHandle);
- var
- pWE: WEPtr;
- caretInterval, sleepTime: LongInt;
- saveWELock: Boolean;
- begin
-
- { lock the WE record }
- saveWELock := _WESetHandleLock(hWE, true);
- pWE := hWE^;
-
- { the caret blinks only if we're active and the selection point is empty }
- if (BTST(pWE^.flags, weFActive) and (pWE^.selStart = pWE^.selEnd)) then
- begin
-
- { the low-memory global variable CaretTime contains the preferred interval }
- { between successive inversions of the caret }
- caretInterval := GetCaretTime;
-
- { calculate how many ticks we can sleep before we need to invert the caret }
- { the caretTime field of the WE record contains the time of the last inversion }
- sleepTime := caretInterval - (TickCount - pWE^.caretTime);
-
- { if sleepTime has gone negative, invert the caret }
- if (sleepTime <= 0) then
- begin
- _WEBlinkCaret(hWE);
- sleepTime := caretInterval;
- end;
-
- end
- else
-
- { if we don't need to blink the caret, we can sleep forever }
- sleepTime := maxLongInt;
-
- { return sleepTime to the caller if maxSleep isn't NIL }
- if (@maxSleep <> nil) then
- maxSleep := sleepTime;
-
- { unlock the WE record }
- IgnoreBoolean(_WESetHandleLock(hWE, saveWELock));
-
- end; { WEIdle }
-
- procedure WEUpdate (updateRgn: RgnHandle;
- hWE: WEHandle);
- var
- pWE: WEPtr;
- firstLine, lastLine: LongInt;
- auxRect: Rect;
- saveClip, auxRgn: RgnHandle;
- savePort: GrafPtr;
- saveWELock: Boolean;
- begin
-
- { lock the WE record }
- saveWELock := _WESetHandleLock(hWE, true);
- pWE := hWE^;
-
- { set up the port }
- GetPort(savePort);
- SetPort(pWE^.port);
-
- { save the clip region }
- saveClip := NewRgn;
- GetClip(saveClip);
-
- { clip to the insersection between updateRgn and the view rectangle }
- { (updateRgn may be NIL; in this case, just clip to the view rectangle) }
- auxRgn := NewRgn;
- if (updateRgn <> nil) then
- SectRgn(updateRgn, pWE^.viewRgn, auxRgn)
- else
- CopyRgn(pWE^.viewRgn, auxRgn);
- SetClip(auxRgn);
-
- if (EmptyRgn(auxRgn) = false) then
- begin
-
- { set auxRect to the bounding box of the update region (clipped to the view rectangle) }
- auxRect := auxRgn^^.rgnBBox;
-
- { find out which lines need to be redrawn }
- firstLine := _WEPixelToLine(auxRect.top - pWE^.destRect.top, hWE);
- lastLine := _WEPixelToLine((auxRect.bottom - 1) - pWE^.destRect.top, hWE);
-
- { draw them (if updateRgn is NIL, erase each line rectangle before redrawing) }
- _WEDrawLines(firstLine, lastLine, (updateRgn = nil), hWE);
-
- { hilite the selection range or draw the caret (only if active) }
- if (pWE^.selStart < pWE^.selEnd) then
- _WEHiliteRange(pWE^.selStart, pWE^.selEnd, hWE)
- else if BTST(pWE^.flags, weFCaretVisible) then
- begin
- _WEBlinkCaret(hWE);
- BSET(pWE^.flags, weFCaretVisible);
- end;
-
- end; { if not empty }
-
- DisposeRgn(auxRgn);
-
- { restore the clip region }
- SetClip(saveClip);
- DisposeRgn(saveClip);
-
- { restore the port }
- SetPort(savePort);
-
- { unlock the WE record }
- IgnoreBoolean(_WESetHandleLock(hWE, saveWELock));
-
- end; { WEUpdate }
-
- procedure WEDeactivate (hWE: WEHandle);
- var
- pWE: WEPtr;
- saveWELock: Boolean;
- begin
-
- { lock the WE record }
- saveWELock := _WESetHandleLock(hWE, true);
- pWE := hWE^;
-
- { do nothing if we are already inactive }
- if (BTST(pWE^.flags, weFActive)) then
- begin
-
- { hide the selection range or the caret }
- _WEHiliteRange(pWE^.selStart, pWE^.selEnd, hWE);
- if BTST(pWE^.flags, weFCaretVisible) then
- _WEBlinkCaret(hWE);
-
- { clear the active flag }
- BCLR(pWE^.flags, weFActive);
-
- { frame the selection }
- _WEHiliteRange(pWE^.selStart, pWE^.selEnd, hWE);
-
- { dispose of the offscreen graphics world, if any }
- if (pWE^.offscreenPort <> nil) then
- begin
- DisposeGWorld(GWorldPtr(pWE^.offscreenPort));
- pWE^.offscreenPort := nil;
- end;
-
- { notify Text Services }
- if (pWE^.tsmReference <> nil) then
- IgnoreShort(DeactivateTSMDocument(pWE^.tsmReference));
-
- end;
-
- { unlock the WE record }
- IgnoreBoolean(_WESetHandleLock(hWE, saveWELock));
-
- end; { WEDeactivate }
-
- procedure WEActivate (hWE: WEHandle);
- var
- pWE: WEPtr;
- saveWELock: Boolean;
- begin
-
- { lock the WE record }
- saveWELock := _WESetHandleLock(hWE, true);
- pWE := hWE^;
-
- { do nothing if we are already active }
- if (not BTST(pWE^.flags, weFActive)) then
- begin
-
- { remove the selection frame }
- _WEHiliteRange(pWE^.selStart, pWE^.selEnd, hWE);
-
- { set the active flag }
- BSET(pWE^.flags, weFActive);
-
- { show the selection range }
- _WEHiliteRange(pWE^.selStart, pWE^.selEnd, hWE);
-
- { notify Text Services }
- if (pWE^.tsmReference <> nil) then
- IgnoreShort(ActivateTSMDocument(pWE^.tsmReference));
-
- end;
-
- { unlock the WE record }
- IgnoreBoolean(_WESetHandleLock(hWE, saveWELock));
-
- end; { WEActivate }
-
- function WEIsActive (hWE: WEHandle): Boolean;
- begin
-
- { return TRUE iff the specified WE instance is currently active }
- WEIsActive := BTST(hWE^^.flags, weFActive);
-
- end; { WEIsActive }
-
- procedure CallScrollProc (hWE: WEHandle;
- scrollProc: ProcPtr);
- inline
- $205F, { movea.l (sp)+, a0 }
- $4E90; { jsr (a0) }
-
- procedure WEScroll (hOffset, vOffset: LongInt;
- hWE: WEHandle);
- var
- pWE: WEPtr;
- viewRect: Rect;
- updateRgn: RgnHandle;
- savePort: GrafPtr;
- hideOutline, saveWELock: Boolean;
- begin
-
- { do nothing if both scroll offsets are zero }
- if ((hOffset = 0) and (vOffset = 0)) then
- Exit(WEScroll);
-
- { lock the WE record }
- saveWELock := _WESetHandleLock(hWE, true);
- pWE := hWE^;
-
- { hide the caret if it's showing }
- if BTST(pWE^.flags, weFCaretVisible) then
- _WEBlinkCaret(hWE);
-
- { set up the port }
- GetPort(savePort);
- SetPort(pWE^.port);
-
- { if we're inactive and outline highlighting is on, we have to temporarily }
- { hide the selection outline while scrolling to avoid a cosmetic bug }
- hideOutline := false;
- if (not BTST(pWE^.flags, weFActive)) then
- if (BTST(pWE^.flags, weFOutlineHilite)) then
- begin
- hideOutline := true;
- _WEHiliteRange(pWE^.selStart, pWE^.selEnd, hWE);
- BCLR(pWE^.flags, weFOutlineHilite);
- end;
-
- { if we're currently tracking a drag, notify the Drag Manager we're about to scroll }
- if (pWE^.currentDrag <> kNullDrag) then
- IgnoreShort(DragPreScroll(pWE^.currentDrag, hOffset, vOffset));
-
- viewRect := pWE^.viewRgn^^.rgnBBox;
- updateRgn := NewRgn;
-
- { offset the destination rectangle by the specified amount }
- WEOffsetLongRect(pWE^.destRect, hOffset, vOffset);
-
- { scroll the view rectangle }
- ScrollRect(viewRect, hOffset, vOffset, updateRgn);
-
- { redraw the exposed region }
- WEUpdate(updateRgn, hWE);
- DisposeRgn(updateRgn);
-
- { notify the Drag Manager }
- if (pWE^.currentDrag <> kNullDrag) then
- IgnoreShort(DragPostScroll(pWE^.currentDrag));
-
- { redraw the selection outline, if hidden }
- if (hideOutline) then
- begin
- BSET(pWE^.flags, weFOutlineHilite);
- _WEHiliteRange(pWE^.selStart, pWE^.selEnd, hWE);
- end;
-
- { restore the port }
- SetPort(savePort);
-
- { unlock the WE record }
- IgnoreBoolean(_WESetHandleLock(hWE, saveWELock));
-
- end; { WEScroll }
-
- function _WEScrollIntoView (offset: LongInt;
- hWE: WEHandle): Boolean;
- var
- pWE: WEPtr;
- thePoint: LongPoint;
- lineHeight: Integer;
- hScroll, vScroll, temp: LongInt;
- begin
- pWE := hWE^;
-
- { do nothing if automatic scrolling is disabled }
- if (not BTST(pWE^.flags, weFAutoScroll)) then
- Exit(_WEScrollIntoView);
-
- { find the selection point }
- WEGetPoint(offset, thePoint, lineHeight, hWE);
-
- { assume no scrolling is needed }
- _WEScrollIntoView := false;
- vScroll := 0;
- hScroll := 0;
-
- { determine if we need to scroll vertically }
- if (thePoint.v < pWE^.viewRect.top) or (thePoint.v + lineHeight >= pWE^.viewRect.bottom) then
- begin
-
- { calculate the amount of vertical scrolling needed to center the selection into view }
- vScroll := BSR(pWE^.viewRect.top + pWE^.viewRect.bottom, 1) - thePoint.v;
-
- { we'd like to superimpose the bottom margins of the dest/view rects, if possible }
- temp := pWE^.viewRect.bottom - pWE^.destRect.bottom;
- if (temp > vScroll) then
- vScroll := temp;
-
- { but we also have to make sure the dest top isn't scrolled below the view top }
- temp := pWE^.viewRect.top - pWE^.destRect.top;
- if (temp < vScroll) then
- vScroll := temp;
-
- end;
-
- { determine if we need to scroll horizontally }
- if (thePoint.h - 1 < pWE^.viewRect.left) or (thePoint.h >= pWE^.viewRect.right) then
- begin
-
- { calculate the amount of horizontal scrolling needed to center the selection into view }
- hScroll := BSR(pWE^.viewRect.left + pWE^.viewRect.right, 1) - thePoint.h;
-
- { we'd like to superimpose the right margins of the dest/view rects, if possible }
- temp := pWE^.viewRect.right - pWE^.destRect.right;
- if (temp > hScroll) then
- hScroll := temp;
-
- { but we also have to make sure the dest left isn't scrolled to the right of the view left }
- temp := pWE^.viewRect.left - pWE^.destRect.left;
- if (temp < hScroll) then
- hScroll := temp;
-
- end;
-
- { scroll the text if necessary }
- if ((vScroll <> 0) or (hScroll <> 0)) then
- begin
- _WEScrollIntoView := true;
- WEScroll(hScroll, vScroll, hWE);
- end;
-
- { call the scroll callback, if any }
- if (pWE^.scrollProc <> nil) then
- CallScrollProc(hWE, pWE^.scrollProc);
-
- end; { _WEScrollIntoView }
-
- procedure WESelView (hWE: WEHandle);
- var
- pWE: WEPtr;
- offset: LongInt;
- saveWELock: Boolean;
- begin
-
- { lock the WE record }
- saveWELock := _WESetHandleLock(hWE, true);
- pWE := hWE^;
-
- { scroll the free endpoint of the selection into view }
- if (BTST(pWE^.flags, weFAnchorIsEnd)) then
- offset := pWE^.selStart
- else
- offset := pWE^.selEnd;
- IgnoreBoolean(_WEScrollIntoView(offset, hWE));
-
- { unlock the WE record }
- IgnoreBoolean(_WESetHandleLock(hWE, saveWELock));
-
- end; { WESelView }
-
- end.